import axios, {AxiosError, AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig} from 'axios'

import {createGlobalState, useStorage} from '@vueuse/core'

export const STORAGE_AUTHORIZE_KEY = 'Authorization'

export const useAuthorization = createGlobalState(() => useStorage<null | string>(STORAGE_AUTHORIZE_KEY, null))


async function requestHandler(config: InternalAxiosRequestConfig): Promise<InternalAxiosRequestConfig> {
    const token = useAuthorization()

    if (token.value)
        config.headers.set(STORAGE_AUTHORIZE_KEY, 'Bearer '+token.value)

    return config
}

const instance: AxiosInstance = axios.create({
    baseURL: '/api',
    timeout: 60000,
    headers: {'Content-Type': 'application/json;charset=UTF-8'},
})
instance.interceptors.request.use(requestHandler)

interface AxiosOptions<T> {
    url: string
    params?: T
    data?: T
}

export interface RequestConfigExtra {
    token?: boolean
    customDev?: boolean
    loading?: boolean
}

function instancePromise<R = any, T = any>(options: AxiosOptions<T> & RequestConfigExtra): Promise<R> {
    // const { loading } = options
    return new Promise((resolve, reject) => {
        instance.request(options).then((res) => {
            resolve(res as any)
        }).catch((e: Error | AxiosError) => {
            reject(e)
        })
            .finally(() => {
                // if (loading)
                //     axiosLoading.closeLoading()
            })
    })
}

export function useGet<R = any, T = any>(url: string, params?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<R> {
    const options = {url, params, method: 'GET', ...config,}
    return instancePromise<R, T>(options)
}

export function usePost<R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<R> {
    const options = {url, data, method: 'POST', ...config,}
    return instancePromise<R, T>(options)
}

export function usePut<R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<R> {
    const options = {url, data, method: 'PUT', ...config,}
    return instancePromise<R, T>(options)
}

export function useDelete<R = any, T = any>(url: string, data?: T, config?: AxiosRequestConfig & RequestConfigExtra): Promise<R> {
    const options = {url, data, method: 'DELETE', ...config,}
    return instancePromise<R, T>(options)
}